package com.apimarket.controller;

import com.apimarket.entity.ApiInterfaceWithBLOBs;
import com.apimarket.entity.ApiSet;
import com.apimarket.entity.PageModel;
import com.apimarket.entity.Result;
import com.apimarket.entity.kong.KeyAuthCredential;
import com.apimarket.entity.kong.Route;
import com.apimarket.entity.vo.ApiInterfaceWithBOLOBsPath;
import com.apimarket.entity.vo.ApiSetInterfaces;
import com.apimarket.service.ApiService;
import com.apimarket.service.ConsumerService;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

/**
 * api集与api接口提交(同步两数据库)、修改，删除控制层
 *
 * @author yyc
 */
@RestController
@RequestMapping("/api")
public class ApiController {
    @Autowired
    private ApiService apiService;

    private static final String IO_ERROR = "网络异常";
    @Autowired
    private ConsumerService consumerService;

    /**
     * api接口具体提交流程：
     * 先提交至kong的数据库，提交无误后，再输入例如请求参数，相应参数这些内容
     * 需要将第一步的信息待入至第二步的信息有：
     * 接口id、接口名、所属接口集id、接口请求方法、接口url（需要与接口集url联动处理，即请求一波所属接口集的url）
     *
     * @param record  接口详细信息对象
     * @param request 请求对象，后续从请求对象中获取user_id
     */
    @RequestMapping(value = "/interface/submit", method = {RequestMethod.POST})
    public Result<String> submitApiInterfaceDetail(@RequestBody @Validated ApiInterfaceWithBLOBs record,
                                                   HttpServletRequest request) {
        int count = apiService.insertRecord(record);
        return new Result<>("insert " + count + " record successfully", 200, "success");
    }

    /**
     * api集具体提交流程与api接口流程基本一致，两步走
     * 需要将第一步的信息待入至第二步的信息有：
     * 接口集id、接口集名
     *HttpServletRequest对象代表客户端的请求，当客户端通过HTTP协议访问服务器时，
     * HTTP请求头中的所有信息都封装在这个对象中，通过这个对象提供的方法，可以获得客户端请求的所有信息。
     *
     * @param record  接口集详细信息对象
     * @param request 请求对象，后续从请求对象中获取user_id
     */
    @RequestMapping(value = "/set/submit", method = {RequestMethod.POST})
    public Result<String> submitApiSetDetail(@RequestBody @Validated ApiSet record,
                                             HttpServletRequest request) {
        int count = apiService.insertRecord(record);
        return new Result<>("insert " + count + " record successfully", 200, "success");
    }

    /**
     * 获取接口集概览，分页形式
     * 第一次请求时，sumPage应为空，这样额外计算一次总页码
     * 后续发起分页查询，务必带上总页码
     *
     * @param pageNo  所要查询第几页
     * @param sumPage 总页码
     */
    @RequestMapping(value = "/set/list", method = {RequestMethod.GET})
    public Result<PageModel<ApiSet>> getPageList(@RequestParam Integer pageNo,
                                                 @RequestParam(required = false) Long sumPage) {
        List<ApiSet> sets = apiService.getPageSetDetail(pageNo);
        Long sumCount = apiService.getCount();
        sumPage = sumCount / ApiService.pageSize;
        PageModel<ApiSet> pageModel = new PageModel<>(sumCount, pageNo, ApiService.pageSize, sets);
        return new Result<>(pageModel, 200, "success");
    }



    /**
     * 分页条件查询获取接口集的业务数据信息
     * @param pageSize
     * @param page
     * @param type 接口集种类
     * @param name 接口集名字
     * @return
     */
    @RequestMapping(value = "/set/pageObject", method = {RequestMethod.GET})
    public Result<PageInfo<ApiSet>> getSetPageObject(Integer pageSize,Integer page,Integer type,String name){
        PageInfo<ApiSet> pageObject=apiService.findSetPageObject(pageSize,page,type,name);
        return new Result<PageInfo<ApiSet>>(pageObject,200,"success");
    }


    /**
     * 根据api集id获取其包含的接口
     *
     * @param serviceId api集id
     */
    @RequestMapping(value = "/interface/list/service", method = {RequestMethod.GET})
    public Result<List<ApiInterfaceWithBLOBs>> getInterfaceList(@RequestParam String serviceId) {
        List<ApiInterfaceWithBLOBs> interfaceList = apiService.getListViaService(serviceId);
        return new Result<>(interfaceList, 200, "success");
    }


    /**
     * 一次性提交api集至两个数据库的同步接口
     * 其中api集url部分必须以 / 结尾，涉及route的path属性处理
     *这里的添加接口集的方法传入的url,应该是如果传入了url就会自动将他分割为pong中添加service需要的字段
     * 而且这个接口对应着两个页面
     * @param record 封装了本业务数据库所需字段及提交至Kong数据库的两个字段name与url
     * @see com.apimarket.service.ApiService
     */
    @RequestMapping(value = "/set/submitAll", method = {RequestMethod.POST})
    public Result<String> submitApiSetDisposable(@Validated ApiSet record, MultipartFile imageFile) throws URISyntaxException {
        try {
            apiService.insertRecordDisposableAndFile(record,imageFile);
            //apiService.insertRecordDisposable(record);
            return new Result<>("success", 200, "success");
        } catch (IOException e) {
            return new Result<>(IO_ERROR, 400, "fail");
        }catch(URISyntaxException e){
            e.printStackTrace();
            return new Result<>(IO_ERROR, 400, "fail");
        }
    }

    /**
     * 修改某个接口集，需要修改业务数据库和kong数据库，需要保证跨数据库的事务一致
     * @param apiSet
     * @param imageFile
     * @return
     */
    @RequestMapping(value="/set/update",method={RequestMethod.POST})
    public Result<String> updateApiSet(ApiSet apiSet,MultipartFile imageFile) throws IOException, URISyntaxException {
        try{
            apiService.updateApiSet(apiSet,imageFile);
            return new Result<>("success",200,"success");
        }catch(IOException e){
            return new Result<>(IO_ERROR, 400, "fail");
        }
    }

    /**
     * 查询属于某个service下的所有route信息
     * @param id service id
     * @return
     */
    @RequestMapping("/set/listRoutesByServiceId")
    public Result<List<Route>> listRoutesByServiceId(String id) throws IOException, URISyntaxException {
        try{
            List<Route> list=apiService.listRoutesByServiceId(id);
            return new Result<>(list,200,"success");
        }catch(IOException e){
            return new Result<>(null, 400, "fail");
        }

    }

    /**
     * 查询某个接口集的详细信息以及数据这个接口集的所有接口的详细信息
     * @param id 接口集id
     * @return
     */
    @RequestMapping(value="/set/detailAndChildRoute",method={RequestMethod.POST})
    public Result<ApiSetInterfaces> findSetDetailAndChildRoute(String id){
        ApiSetInterfaces result=apiService.findSetDetailAndChildRoute(id);
        return new Result<>(result,200,"success");
    }


    /**
     * 这是查询一个接口集的详细数据，查的是业务数据库。BUT我现在就直接返回这个url了
     * 懒得搞了
     * @param userId
     * @param path 由/api/set/detailAndChildRoute interfaces下url返回
     * @return
     */
    @RequestMapping(value="/set/getRequestPath",method={RequestMethod.POST})
    public Result<String> getRequestPath(String userId,String path) throws IOException,
            URISyntaxException {
        //获得该用户的apikey，这个接口返回的是一个列表，可据我观察一般都是一个用户一个apikey
        List<KeyAuthCredential> consumerKeyAuth =
                consumerService.getConsumerKeyAuth(userId);
        //先这么写着
        String apiKey = consumerKeyAuth.get(0).getKey();

        String result = path+"?apikey="+apiKey;
        return new Result<>(result,200,"success");

    }
    @RequestMapping(value="/set/findDetailById")
    public Result<ApiSet> findOneDetailById(String id){
        ApiSet apiSet=apiService.findOneDetailById(id);
        return new Result<>(apiSet,200,"success");
    }


    /**
     * 一次性删除两个数据库api集记录同步接口
     * 删除前需要判断，这个service底下有没有绑定route，如果绑定了就不给删
     *
     * @param id api集id
     */
    @RequestMapping(value = "/set/delete")
    public Result<String> deleteApiSetDisposable(@RequestParam String id) throws URISyntaxException {
        try {
            apiService.deleteApiSetRecordDisposable(id);
            return new Result<>("success", 200, "success");
        } catch (IOException e) {
            return new Result<>(IO_ERROR, 400, "fail");
        }
    }


    /**
     * 一次性提交api接口数据至两个数据库的同步接口
     * 提交的url无需需以 / 结尾，注意与api集的url区分，涉及route的path属性处理
     *
     * @param record api接口相关信息
     * @see com.apimarket.service.ApiService
     */
   /* @RequestMapping(value = "/interface/submitAll", method = {RequestMethod.POST})
    public Result<String> submitApiInterfaceDisposable(@RequestBody @Validated ApiInterfaceWithBLOBs record) throws URISyntaxException {
        try {
            apiService.insertRecordDisposable(record);
            return new Result<>("success", 200, "success");
        } catch (IOException e) {
            return new Result<>(IO_ERROR, 400, "fail");
        }
    }*/

    /**
     * 添加api接口集，需要传递这个接口集所对应的serviceid,routeid,以及route中的List<String>path
     * @param record
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    @RequestMapping(value="/interface/add",method={RequestMethod.POST})
    public Result<String> addInterface(@Validated ApiInterfaceWithBOLOBsPath record, MultipartFile imageFile) throws URISyntaxException {
        try {
            apiService.addInterface(record,imageFile);
            return new Result<>("success", 200, "success");
        } catch (IOException e) {
            return new Result<>(IO_ERROR, 400, "fail");
        }
    }



    @RequestMapping(value="/interface/update",method = {RequestMethod.POST})
    public Result<String> updateInterface(@Validated ApiInterfaceWithBOLOBsPath record,MultipartFile imageFile){
        apiService.updateInterface(record,imageFile);
        return new Result<>("success", 200, "success");
    }

    /**
     * 删除api接口
     *
     * @param id api接口id
     */
    @RequestMapping(value = "/interface/delete")
    public Result<String> deleteApiInterfaceDisposable(@RequestParam String id) throws URISyntaxException {
        try {
            apiService.deleteApiInterfaceRecordDisposable(id);
            return new Result<>("success", 200, "success");
        } catch (IOException e) {
            return new Result<>(IO_ERROR, 400, "fail");
        }
    }

    /**
     * 根据接口id查询接口详细信息
     * @param id
     * @return
     */
    @RequestMapping("/interface/getDetailById")
    public Result<ApiInterfaceWithBLOBs> getInterfaceById(String id){
        ApiInterfaceWithBLOBs result=apiService.getInterfaceById(id);
        return new Result<>(result, 200, "success");
    }

}
